package com.overlord.im.commons.message;

import com.overlord.im.commons.constant.AckType;
import com.overlord.im.commons.constant.MsgType;
import com.overlord.im.commons.constant.SystemType;
import com.overlord.im.commons.exception.ImException;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

import java.io.IOException;
import java.util.Optional;

/**
 * @ClassName OverlordProtocol
 * @Author wuwei
 * @Description NONE
 * @Date 2020/5/29 10:26
 **/
public class OverlordProtocol implements Protocol {

    private MessageProtocolConverter messageProtocolConverter;

    public OverlordProtocol(MessageProtocolConverter messageProtocolConverter) {
        this.messageProtocolConverter = messageProtocolConverter;
    }

    @Override
    public void encode(ByteBuf out, OverlordImMessage message) throws IOException {
        out.writeByte(OVERLORD_PACKET);
        out.writeByte(message.getVersion());
        out.writeLong(message.getSequenceId());
        out.writeByte(message.getMsgType().getCode());
        out.writeByte(Optional.ofNullable(message.getAckType()).orElse(AckType.NONE).getCode());
        out.writeByte(Optional.ofNullable(message.getSystemType()).orElse(SystemType.NONE).getCode());
        messageProtocolConverter.encode(out, message);
    }

    @Override
    public OverlordImMessage decode(ByteBuf in) throws IOException {
        byte overlordPacket = in.readByte();
        if (overlordPacket != OVERLORD_PACKET) {
            throw new ImException("异常的请求包");
        }
        byte version = in.readByte();
        long sequenceId = in.readLong();
        byte msgType = in.readByte();
        byte ackType = in.readByte();
        byte systemType = in.readByte();
        int length = in.readMedium();
        if (length > 0) {
            ByteBuf buffer = Unpooled.buffer(length);
            in.readBytes(buffer);
            OverlordImMessage message =
                    messageProtocolConverter.decode(buffer, version, msgType, ackType, systemType, sequenceId);
            return message;
        } else {
            return OverlordImMessage.builder().version(version).sequenceId(sequenceId)
                    .msgType(MsgType.fromCode(msgType)).ackType(AckType.fromCode(ackType)).build();
        }
    }
}
